#!/bin/sh

version=
default=0
timeout=5
verbose=0

conf=/boot/extlinux.conf
myconf=/etc/update-extlinux.conf

# read in extlinux settings
if [ -f "$myconf" ]; then
	. $myconf
fi

everbose() {
	if [ "$verbose" = "0" ]; then
		return
	fi

	echo $*
}

ewarn() {
	echo "WARNING:" $@ >&2
}

eerror() {
	echo "ERROR:" $@ >&2
	return 1
}

usage() {
	echo "usage: $0 [-v|--verbose] [--warn-only]"
}

while [ $# -gt 0 ]; do
	opt="$1"
	shift
	case "$opt" in
	-v|--verbose)
		verbose=1
		;;
	--warn-only)
		warn_only=1
		;;
	--)
		break
		;;
	-*)
		usage
		exit 1
		;;
	esac
done

everbose "Updating extlinux configuration."

if [ "x$root" = "x" ]; then
	ewarn "Root device is not specified in $myconf."
	blkid_export=$(blkid -o export /dev/root)
	if [ -n "$blkid_export" ]; then
		export $blkid_export
	fi
	if [ -z "$UUID" ]; then
		# try parse /proc/mount for mounted /
		dev=$(awk '$2 == "/" {dev=$1} END {print dev}' /proc/mounts)
		if [ -n "$dev" ]; then
			blkid_export=$(blkid -o export $dev)
			if [ -n "$blkid_export" ]; then
				export "$blkid_export"
			fi
		fi
	fi
	if [ -z "$UUID" ]; then
		if [ -z "$dev" ]; then
			if [ -n "$warn_only" ]; then
				ewarn "Failed to detect root device. extlinux.conf is not updated"
				exit 0
			else
				eerror "Failed to detect root device"
				exit 1
			fi
		else
			root=$dev
		fi
	else
		root=UUID=$UUID
	fi
	everbose "Root device is: $root"
fi

rtimeout=$(( ${timeout} * 10 ))
syslinux_menu=menu.c32
menu_hidden=

# vesa menu has been requested?
if [ "$vesa_menu" = "1" ]; then
	syslinux_menu=vesamenu.c32
fi

umask 0022
rm -f $conf.new
echo "# Generated by update-extlinux $version" > $conf.new
if [ -n "$serial_port" ]; then
	echo "SERIAL $serial_port ${serial_baud:-115200}" >> $conf.new
fi
echo "DEFAULT $syslinux_menu" >> $conf.new
echo "PROMPT 0" >> $conf.new
echo "MENU TITLE Alpine/$(uname -s) Boot Menu" >> $conf.new
if [ "$hidden" = "1" ]; then
	echo "MENU HIDDEN" >> $conf.new
fi
echo "MENU AUTOBOOT Alpine will be booted automatically in # seconds." >> $conf.new
echo "TIMEOUT $rtimeout" >> $conf.new

lst=0
if [ -f "/boot/xen.gz" ]; then
	for kernel in $(find /boot -name "vmlinuz-*" -type f); do
		tag=$(basename $kernel | cut -b9-)
		everbose "Found Xen hypervisor: /boot/xen.gz, kernel: $kernel"

		if [ -f "/boot/initramfs-$tag" ]; then
			everbose "Found initramfs: /boot/initramfs-$tag"
			initramfs="initramfs-$tag"
		else
			initramfs=
		fi
		initramfs_stage="${initramfs:+---} $initramfs"

		if [ -f "/boot/amd-ucode.img" ]; then
			everbose "Found microcode for AMD CPUs: /boot/amd-ucode.img"
			ucode_image_amd="amd-ucode.img"
			case "$xen_opts" in
				*ucode=scan* ) ;;
				* ) xen_opts="$xen_opts ucode=scan" ;;
			esac
		fi
		if [ -f "/boot/intel-ucode.img" ]; then
			everbose "Found microcode for Intel CPUs: /boot/intel-ucode.img"
			ucode_image_intel="intel-ucode.img"
			case "$xen_opts" in
				*ucode=scan* ) ;;
				* ) xen_opts="$xen_opts ucode=scan" ;;
			esac
		fi
		ucode_image_stage="${ucode_image_amd:+---} $ucode_image_amd ${ucode_image_intel:+---} $ucode_image_intel"

		label=xen-$(grep -w -l $tag /usr/share/kernel/*/kernel.release \
				| cut -d/ -f5)
		if [ "$label" = "xen-" ]; then
			label=xen-$lst
		fi

		dom0_kernel_stage="--- $(basename $kernel) root=$root modules=${modules}${TYPE:+,$TYPE} $default_kernel_opts"

		echo "LABEL $label" >> $conf.new
		if [ "$label" = "$default" ]; then
			echo "  MENU DEFAULT" >> $conf.new
		fi
		echo "  MENU LABEL Xen + Linux $tag" >> $conf.new
		echo "  COM32 mboot.c32" >> $conf.new
		echo "  APPEND xen.gz $xen_opts $dom0_kernel_stage $initramfs_stage $ucode_image_stage" >> $conf.new
		echo "" >> $conf.new
		lst=$(($lst + 1))
	done
fi

for kernel in $(find /boot -name "vmlinuz*" -type f); do
	case $kernel in
	*vmlinuz) tag=vanilla;;
	*vmlinuz-*)  tag=$(basename $kernel | cut -b9-);;
	*) continue;;
	esac
	everbose "Found kernel: $kernel"
	label=$(grep -w -l $tag /usr/share/kernel/*/kernel.release | cut -d/ -f5)
	if [ -z "$label" ]; then
		if [ "$tag" = vanilla ]; then
			label="vanilla"
		else
			label=$lst
		fi
	fi
	echo "LABEL $label" >> $conf.new
	if [ "$label" = "$default" ]; then
		echo "  MENU DEFAULT" >> $conf.new
	fi
	echo "  MENU LABEL Linux $tag" >> $conf.new
	echo "  LINUX $(basename $kernel)" >> $conf.new
	initrd=
	if [ -f "/boot/initramfs-$tag" ]; then
		everbose "Found initramfs: /boot/initramfs-$tag"
		initrd="initramfs-$tag"
	fi
	if [ -f "/boot/amd-ucode.img" ]; then
		everbose "Found microcode for AMD CPUs: /boot/amd-ucode.img"
		initrd="amd-ucode.img${initrd:+,}${initrd}"
	fi
	if [ -f "/boot/intel-ucode.img" ]; then
		everbose "Found microcode for Intel CPUs: /boot/intel-ucode.img"
		initrd="intel-ucode.img${initrd:+,}${initrd}"
	fi
	echo "  INITRD ${initrd}" >> $conf.new
	echo "  APPEND root=$root modules=${modules}${TYPE:+,$TYPE} $default_kernel_opts" >> $conf.new
	echo "" >> $conf.new
	lst=$(($lst + 1))
done

if [ -n "$password" ]; then
	echo "NOESCAPE 1" >> $conf.new
	echo "MENU MASTER PASSWD $password" >> $conf.new
	echo "" >> $conf.new
	chmod o-r $conf.new
fi

everbose "$lst entries found."

for entry in /etc/update-extlinux.d/*; do
	[ -f "$entry" ] && { cat $entry; echo ""; } >> $conf.new
done

echo "MENU SEPARATOR" >> $conf.new
echo "" >> $conf.new

if [ -f "/boot/hdt.c32" ]; then
	everbose "Found Hardware Detection Tool: /boot/hdt.c32"
	echo "LABEL hdt" >> $conf.new
	echo "  MENU LABEL Hardware info" >> $conf.new
	if [ -n "$password" ]; then
		echo "  MENU PASSWD" >> $conf.new
	fi
	echo "  COM32 hdt.c32" >> $conf.new
	if [ -f "/boot/memtest" ]; then
		everbose "Found memtest86+: /boot/memtest"
		echo "  APPEND memtest=memtest" >> $conf.new
	fi
	echo "" >> $conf.new
elif [ -f "/boot/memtest" ]; then
	everbose "Found memtest86+: /boot/memtest"
	echo "LABEL memtest" >> $conf.new
	echo "  MENU LABEL Memtest86+" >> $conf.new
        echo "  KERNEL memtest" >> $conf.new
	echo "" >> $conf.new
fi

for i in reboot poweroff; do
	[ -f "/boot/$i.c32" ] || continue
	everbose "Found $i"
	# make first char capital
	cap=$( echo $i | awk '{sub(".", substr(toupper($0),1,1), $0); print}' )
	echo "LABEL $i" >> $conf.new
	echo "  MENU LABEL $cap" >> $conf.new
        echo "  COM32 $i.c32" >> $conf.new
	echo "" >> $conf.new
done

if cmp -s $conf.new $conf; then
	everbose "Configuration unchanged."
	rm $conf.new
fi

if [ "$overwrite" != "1" ]; then
	exit 0
elif [ -f "$conf.new" ]; then
	# keep a backup just in case
	if [ -f "$conf" ]; then
		mv $conf $conf.old
	fi

	mv $conf.new $conf
fi

everbose "Installing libutil.c32 libcom32.c32 mboot.c32 menu.c32 vesamenu.c32 to /boot."
cp /usr/share/syslinux/libutil.c32 \
	/usr/share/syslinux/libcom32.c32 \
	/usr/share/syslinux/mboot.c32 \
	/usr/share/syslinux/menu.c32 \
	/usr/share/syslinux/vesamenu.c32 \
	/boot

case "$(stat -f -c '%T' /boot)" in
ext*) extlinux --update /boot || [ -n "$warn_only" ];;
esac

